package com.example.demo.service.Impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.WordsMapper;
import com.example.demo.pojo.Schedule;
import com.example.demo.pojo.UserLike;
import com.example.demo.pojo.Word;
import com.example.demo.pojo.getWords;
import com.example.demo.service.IWordsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author luolinila
 */
@Service
public class WordsServiceImpl extends ServiceImpl<WordsMapper, Word> implements IWordsService {

    @Autowired
    private WordsMapper wordsMapper;
    @Qualifier("redisTemplate")
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Word getWordsBySpell(String spell) {
        Word word = (Word) redisTemplate.opsForValue().get("word_" + spell);
        if (word == null) {
            word = wordsMapper.selectWordsBySpell(spell);
            if (word == null) {
                return null;
            }
            redisTemplate.opsForValue().set("word_" + spell, word, 1, TimeUnit.DAYS);
        }
        return word;
    }

    @Override
    public Integer getLearn(Integer userId, String bookName) {
        Integer learn = (Integer) redisTemplate.opsForValue().get("user_learn_" + userId + bookName);
        if (learn == null) {
            learn = wordsMapper.selectLearn(new Schedule(userId, bookName));
            if (learn == null) {
                wordsMapper.insertSchedule(new Schedule(userId, bookName, 1, 1));
                redisTemplate.opsForValue().set("user_learn_" + userId + bookName, 1, 1,TimeUnit.DAYS);
                return 1;
            }
            redisTemplate.opsForValue().set("user_learn_" + userId + bookName, learn, 1,TimeUnit.DAYS);
        }
        return learn;
    }

    @Override
    public Integer getReview(Integer userId, String bookName) {
        Integer review = (Integer) redisTemplate.opsForValue().get("user_review_" + userId + bookName);
        if (review == null) {
            review = wordsMapper.selectReview(new Schedule(userId, bookName));
            if (review == null) {
                wordsMapper.insertSchedule(new Schedule(userId, bookName, 1, 1));
                redisTemplate.opsForValue().set("user_review_" + userId + bookName, 1, 1,TimeUnit.DAYS);
                return 1;
            }
            redisTemplate.opsForValue().set("user_review_" + userId + bookName, review, 1,TimeUnit.DAYS);
        }
        return review;
    }

    @Override
    public List<Word> getWords(String bookName, Integer count, Integer start) {
        Word word = wordsMapper.selectById(start);
        return wordsMapper.getWords(new getWords(start, word.getWordBook(), count));
    }

    @Override
    public void updateLearn(Integer userId, String bookName, Integer learn) {
        Integer review = getReview(userId, bookName);
        List<Word> list = getWords(bookName, 1, learn);
        wordsMapper.updateSchedule(new Schedule(userId, bookName, list.get(0).getId(), review));
        redisTemplate.opsForValue().set("user_learn_" + userId + bookName, list.get(0).getId(), 1, TimeUnit.DAYS);
    }

    @Override
    public void updateReview(Integer userId, String bookName, Integer review) {
        Integer learn = getLearn(userId, bookName);
        if(review >= learn) {
            wordsMapper.updateSchedule(new Schedule(userId, bookName, learn, learn));
            redisTemplate.opsForValue().set("user_review_" + userId + bookName, learn, 1, TimeUnit.DAYS);
            return;
        }
        List<Word> list = getWords(bookName, 1, review);
        wordsMapper.updateSchedule(new Schedule(userId, bookName, learn, list.get(0).getId()));
        redisTemplate.opsForValue().set("user_review_" + userId + bookName, list.get(0).getId(), 1, TimeUnit.DAYS);
    }

    public List<Integer> getUserLikes(Integer userId) {
        List<Integer> list = (List<Integer>) redisTemplate.opsForValue().get("user_like_" + userId);
        if (list == null) {
            list = wordsMapper.getUserLike(userId);
            if (list == null) {
                return null;
            }
            redisTemplate.opsForValue().set("user_like_" + userId, list, 1, TimeUnit.DAYS);
        }
        return list;
    }

    @Override
    public List<Word> getUserLike(Integer userId) {
        List<Integer> list = getUserLikes(userId);
        List<Word> wordList = new ArrayList<>();
        for(Integer i : list) {
            wordList.add(getById(String.valueOf(i)));
        }
        return wordList;
    }

    @Override
    public void addUserLike(Integer userId, Integer wordId) {
        List<Integer> list = getUserLikes(userId);
        if(!list.contains(wordId)) {
            wordsMapper.addUserLike(new UserLike(userId, wordId));
            list = wordsMapper.getUserLike(userId);
            redisTemplate.opsForValue().set("user_like_" + userId, list, 1, TimeUnit.DAYS);
        }
        updateWordCollection(wordId);
    }

    @Override
    public void deleteUserLike(Integer userId, Integer wordId) {
        List<Integer> list = getUserLikes(userId);
        if(list.contains(wordId)) {
            wordsMapper.deleteUserLike(new UserLike(userId, wordId));
            list = wordsMapper.getUserLike(userId);
            redisTemplate.opsForValue().set("user_like_" + userId, list, 1, TimeUnit.DAYS);
        }
        updateWordCollection(wordId);
    }

    @Override
    public Boolean isUserLike(Integer userId, Integer wordId) {
        List<Integer> list = getUserLikes(userId);
        return list.contains(wordId);
    }

    @Override
    public Integer getWordCollection(Integer wordId) {
        Integer collection = (Integer) redisTemplate.opsForValue().get("word_collection_" + wordId);
        if (collection == null) {
            collection = wordsMapper.getWordCollection(wordId);
            if (collection == null) {
                return 0;
            }
            redisTemplate.opsForValue().set("word_collection_" + wordId, collection, 1, TimeUnit.DAYS);
        }
        return collection;
    }

    @Override
    public void updateWordCollection(Integer wordId) {
        Integer userLike = getWordCollection(wordId);
        if(userLike == 0) {
            userLike = wordsMapper.selectWordCollection(wordId).size();
            if (userLike == 0) {
                return;
            }
            wordsMapper.insertWordCollection(wordId, userLike);
        }
        redisTemplate.opsForValue().set("word_collection_" + wordId, userLike, 1, TimeUnit.DAYS);
    }

    @Override
    public List<Word> getWordsByBook(String bookName) {
        List<Integer> list = (List<Integer>) redisTemplate.opsForValue().get("book_" + bookName);
        if (list == null) {
            list = wordsMapper.selectBookAllWords(bookName);
            redisTemplate.opsForValue().set("book_" + bookName, list, 1, TimeUnit.DAYS);
        }
        List<Word> wordList = new ArrayList<>();
        for(Integer i : list) {
            wordList.add(getById(String.valueOf(i)));
        }
        return wordList;
    }
}
